package com.allenkerr.rpc.client;

import com.allenkerr.rpc.common.RpcRequest;
import com.allenkerr.rpc.common.RpcResponse;
import com.allenkerr.rpc.registry.ServiceDiscovery;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * Rpc代理，用于创建Rpc代理服务。
 * 1. 实现代理，代理业务接口
 * 2. 封装request
 * 3. 实现从zookeeper上获取server地址
 * 4. 调用send方法，向server发送request
 * 5. 接收返回值（response）
 * <p>
 * Created by 小柯(Allen Kerr) on 17.5.23 20:16.
 */
public class RpcProxy {

  private String serverAddress;

  private ServiceDiscovery serviceDiscovery;

  public RpcProxy(String serverAddress) {
    this.serverAddress = serverAddress;
  }

  public RpcProxy(ServiceDiscovery serviceDiscovery) {
    this.serviceDiscovery = serviceDiscovery;
  }

  public <T> T create(Class<?> interfaceClass) {
    InvocationHandler invocationHandler = (proxy, method, args) -> {
      //创建rpcRequest，封装被代理类的属性
      RpcRequest request = new RpcRequest();
      request.setRequestId(UUID.randomUUID().toString());
      //接口名称
      request.setClassName(method.getDeclaringClass().getName());
      //方法名
      request.setMethodName(method.getName());
      //方法参数类型
      request.setParameterTypes(method.getParameterTypes());
      //方法参数
      request.setParameters(args);

      //查找服务
      if (serviceDiscovery != null) {
        //获取服务的地址
        serverAddress = serviceDiscovery.discover();
      }
      String[] array = serverAddress.split(":");
      String host = array[0];
      int port = Integer.parseInt(array[1]);

      //创建netty实现的RpcClient，连接服务端
      RpcClient client = new RpcClient(host, port);
      //通过netty向服务端发送请求
      RpcResponse response = client.send(request);
      //返回信息
      if (response.isError()) {
        //得到的是错误信息
        throw response.getError();
      }
      return response.getResult();
    };
    return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, invocationHandler);
  }
}

